package org.flexthinker.binding.value.support
{
    import mx.events.PropertyChangeEvent;

    import org.hamcrest.assertThat;
    import org.hamcrest.object.equalTo;

    /**
     *
     */
    public class PropertyChangePublisherImplTest
    {
        private var property:PropertyChangePublisherImpl;
        private var mockBean:MockBean = new MockBean();
        private var listener:PropertyChangeListenerCounter;

        public function PropertyChangePublisherImplTest()
        {
        }

        [Before]
        public function setUp():void
        {
            listener = new PropertyChangeListenerCounter();
        }

        [Test]
        public function testPropertyChangeListener():void
        {
            property = new PropertyChangePublisherImpl( mockBean, "bindableProperty" );
            property.addPropertyChangeListener( listener );
            assertThat( "PropertyChangePublished should have been listening", property.isListening, equalTo( true ) );
            assertThat( "Listener should have not been called", listener.counter, equalTo( 0 ) );

            mockBean.bindableProperty = "HELLO BINDING";
            assertThat( "Listener should have been called", listener.counter, equalTo( 1 ) );

            mockBean.bindableProperty = "HELLO AGAIN";
            assertThat( "Listener should have been called", listener.counter, equalTo( 2 ) );

            property.removeAllListeners();
            assertThat( "listening didn't stop.", property.isListening, equalTo( false ) );
            mockBean.bindableProperty = "NO UPDATE";
            assertThat( "Listener shouldn't have been called", listener.counter, equalTo( 2 ) );

        }

        [Test]
        public function testPropertyChangeOnCustomBindableProperty():void
        {
            property = new PropertyChangePublisherImpl( mockBean, "bindablePropertyWithCustomEvent" );
            property.addPropertyChangeListener( listener );

            property.addPropertyChangeListener(
                new DelegatingPropertyChangeListener(
                    function( event:PropertyChangeEvent ):void
                    {
                        assertThat( event.oldValue, equalTo( null ) );
                        assertThat( event.newValue, equalTo( "HELLO BINDING" ) );
                    } ) );

            assertThat( "PropertyChangePublished should have been listening", property.isListening, equalTo( true ) );
            assertThat( "Listener should have not been called", listener.counter, equalTo( 0 ) );
            mockBean.bindablePropertyWithCustomEvent = "HELLO BINDING";
            assertThat( "Listener should have been called", listener.counter, equalTo( 1 ) );

            property.removeAllListeners();
            property.addPropertyChangeListener( listener );
            mockBean.bindablePropertyWithCustomEvent = "HELLO AGAIN";
            assertThat( "Listener should have been called", listener.counter, equalTo( 2 ) );

            property.removePropertyChangeListener( listener );
            assertThat( "listening didn't stop.", property.isListening, equalTo( false ) );
            mockBean.bindablePropertyWithCustomEvent = "NO UPDATE";
            assertThat( "Listener shouldn't have been called", listener.counter, equalTo( 2 ) );
        }


        [Test]
        public function testCantListenToNonBindableProperties():void
        {
            property = new PropertyChangePublisherImpl( mockBean, "simpleString" );
            property.addPropertyChangeListener( listener );
            assertThat( "Shouldn't have be listening for changes on a property not decorated with [Bindable] metadata",
                        property.isListening, equalTo( false ) );
            mockBean.simpleString = "noBind";
            assertThat( "listened shouldn't have been called", listener.counter, equalTo( 0 ) );
        }


    }
}